<template>
  <div v-if="processDefinitionId || processInstanceId" class="containers">
    <div class="canvas-container">
      <div class="zoom-control">
        <i class="el-icon-aim" @click="handleZoom(0)"></i>
        <i class="el-icon-zoom-out" @click="handleZoom(-0.1)"></i>
        <i class="el-icon-zoom-in" @click="handleZoom(0.1)"></i>
      </div>
      <div class="canvas" ref="canvas" />
    </div>
  </div>
  <EmptyComp v-else />
</template>

<script>
import BpmnModeler from 'bpmn-js/lib/Modeler' // bpmn-js 设计器
import customTranslateModule from '@/views/workflow/utils/bpmn/customTranslate'
  // 对flowable的扩展
import flowableExtensionModule from 'jp-flowable-bpmn-moddle/lib'
import flowableModdle from 'jp-flowable-bpmn-moddle/resources/flowable'
import { defaultXml } from '@/api/workflow/bpmn/model'
import { getProcessImageByDefinitionId, getProcessImage } from '@/api/workflow/bpmn/runtime'
import EmptyComp from '@/components/EmptyComp'

export default {
  components: {
    EmptyComp
  },
  data() {
    return {
      processDefinitionId: '',
      processInstanceId: '',
      bpmnModeler: null,
      element: null,
      bpmnXmlStr: '',
      hisActList: [], // 已历史节点
      currentActList: [], // 当前节点
      scale: 1
    }
  },
  methods: {
    async getModel(processDefinitionId, processInstanceId) { // 获得远程xml
      this.processDefinitionId = processDefinitionId
      this.processInstanceId = processInstanceId
      if (this.processInstanceId) { // 如果流程实例ID存在，则用流程实例ID获取xml
        const res = await getProcessImage(this.processInstanceId)
        this.bpmnXmlStr = res.data.xml
        this.currentActList = res.data.currentActList
        this.hisActList = res.data.hisActList
      } else if (this.processDefinitionId) {
        const res = await getProcessImageByDefinitionId(this.processDefinitionId)
        this.bpmnXmlStr = res.data.xml
        this.currentActList = res.data.currentActList
        this.hisActList = res.data.hisActList
      }
      this.createNewDiagram()
    },
    createNewDiagram() {
      if (this.bpmnModeler) {
        this.bpmnModeler.destroy()
      }
      const canvas = this.$refs.canvas
      // 生成实例
      this.bpmnModeler = new BpmnModeler({
        container: canvas,
        additionalModules: [
          customTranslateModule,
          flowableExtensionModule
        ],
        moddleExtensions: {
          flowable: flowableModdle,
        }
      })
      
      // 禁用节点的单击和双击、拖拽事件，使流程图只读
      const eventBus = this.bpmnModeler.get('eventBus')
      
      delete eventBus._listeners['element.click']
      delete eventBus._listeners['element.dblclick']
      delete eventBus._listeners['drag.move']
      delete eventBus._listeners['drag.start']
      delete eventBus._listeners['drag.init']
      delete eventBus._listeners['shape.move.start']
      delete eventBus._listeners['shape.move.move']
      delete eventBus._listeners['shape.move.end']
      delete eventBus._listeners['connectionSegment.move.start']
      delete eventBus._listeners['connectionSegment.move.move']
      delete eventBus._listeners['connectionSegment.move.end']
      delete eventBus._listeners['bendpoint.move.start']
      delete eventBus._listeners['bendpoint.move.move']
      delete eventBus._listeners['bendpoint.move.end']

      if (canvas && canvas.children && canvas.children[0] && canvas.children[0].children[1] && canvas.children[0].children[1].children[4]) {
        const djsPalette = canvas.children[0].children[1].children[4]
        djsPalette.style['display'] = 'none'
      }
      this.bpmnXmlStr = this.bpmnXmlStr || defaultXml()
      // 需要自动为每一个xml添加flowable属性值，否则xml的头部会自动去掉xmlns:flowable（这个属性值没有其他的含义）
      // if (this.bpmnXmlStr.indexOf('flowable:isFlowable="true"') < 0) {
      //   this.bpmnXmlStr = this.bpmnXmlStr.replace('<process' , '<process flowable:isFlowable="true"')
      // }
      // 将字符串转换成图显示出来
      this.bpmnModeler.importXML(this.bpmnXmlStr, err => {
        if (err) {
          console.error(err)
        } else {
          this.$nextTick(() => {
            const canvas = this.bpmnModeler.get('canvas')
            canvas.zoom('fit-viewport')
            this.scale = canvas._cachedViewbox.scale
          })

          // 标注当前节点颜色
          var elementRegistry = this.bpmnModeler.get('elementRegistry')
          if (this.hisActList && this.hisActList.length) { // 标注历史节点颜色
            this.hisActList.forEach((item, index) => {
              const color = '#409EFF'
              var node = elementRegistry.get(item)
              this.setNodeColor(node, color)
            })
          }
          if (this.currentActList && this.currentActList.length) { // 标注当前节点颜色
            this.currentActList.forEach((item, index) => {
              const color = '#F56C6C'
              var node = elementRegistry.get(item)
              this.setNodeColor(node, color)
            })
          }
        }
      })
    },
    setNodeColor(node, color) {
      if (node) {
        const modeling = this.bpmnModeler.get('modeling')
        modeling.setColor(node, {
          fill: null,
          stroke: color
        })
      }
    },
    handleZoom(flag) {
      this.scale = +(this.scale + flag).toFixed(1)
      if (flag < 0 && this.scale <= 0) {
        return
      }
      if (flag > 0 && this.scale >= 2) {
        return
      }
      const canvas = this.bpmnModeler.get('canvas')
      canvas.zoom(this.scale)
      if (flag === 0) {
        this.$nextTick(() => {
          canvas.zoom('fit-viewport')
          this.scale = canvas._cachedViewbox.scale
        })
      }
    },
    handleMin() {

    },
    handleMax() {

    }
  },
  mounted() {

  }
}
</script>

<style lang="scss">
/*左边工具栏以及编辑节点的样式*/
@import "~bpmn-js/dist/assets/diagram-js.css";
@import "~bpmn-js/dist/assets/bpmn-font/css/bpmn.css";
@import "~bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css";
@import "~bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css";
.containers {
  position: absolute;
  background-color: #fff;
  width: 100%;
  height: 100%;
  .canvas-container {
    position: relative;
    height: 100%;
    .zoom-control {
      position: absolute;
      background: #FAFAFA;
      border-radius: 2px;
      border: solid 1px #E0E0E0;
      padding: 0 15px;
      font-size: 23px;
      z-index: 999;
      i {
        cursor: pointer;
      }
      i + i {
        margin-left: 15px;
      }
    }
  }
  .canvas {
    width: 100%;
    height: 100%;
    // padding-right: 300px;
  }
  .bjs-powered-by {
    display: none;
  }
}
</style>
